/**
 * 
 */

package com.wutianyi.nio.interfaces.impl;

import java.io.IOException;
import java.nio.ByteBuffer;
import java.nio.channels.ByteChannel;

import com.wutianyi.nio.interfaces.BufferFactory;
import com.wutianyi.nio.interfaces.InputQueue;

/**
 * @author wutianyi
 * 
 */
public class InputQueueImpl implements InputQueue {

	private final BufferFactory	bufferFactory;
	private final ByteBuffer	emptyBuffer;
	private ByteBuffer			buffer	= null;

	public InputQueueImpl(BufferFactory bufferFactory) {

		this.bufferFactory = bufferFactory;
		emptyBuffer = ByteBuffer.allocate(0).asReadOnlyBuffer();
	}

	/*
	 * (non-Javadoc)
	 * 
	 * @see com.wutianyi.nio.interfaces.InputQueue#dequeueBytes(int)
	 */
	@Override
	public synchronized ByteBuffer dequeueBytes(int count) {

		if((null == buffer) || (buffer.position() == 0) || (count == 0)) {
			return emptyBuffer;
		}
		int size = Math.min(count, buffer.position());
		ByteBuffer result = ByteBuffer.allocate(size);
		buffer.flip();

		while(result.hasRemaining()) {
			result.put(buffer.get());
		}

		if(buffer.remaining() == 0) {
			bufferFactory.returBuffer(buffer);
			buffer = null;
		}else {
			buffer.compact();
		}

		return result;

	}

	/*
	 * (non-Javadoc)
	 * 
	 * @see com.wutianyi.nio.interfaces.InputQueue#discardBytes(int)
	 */
	@Override
	public void discardBytes(int count) {

		dequeueBytes(count);
	}

	/*
	 * (non-Javadoc)
	 * 
	 * @see com.wutianyi.nio.interfaces.InputQueue#fillFrom(java.nio.channels.ByteChannel)
	 */
	@Override
	public synchronized int fillFrom(ByteChannel channel) throws IOException {

		if(null == buffer) {
			buffer = bufferFactory.newBuffer();
		}
		return channel.read(buffer);
	}

	/*
	 * (non-Javadoc)
	 * 
	 * @see com.wutianyi.nio.interfaces.InputQueue#indexOf(byte)
	 */
	@Override
	public synchronized int indexOf(byte b) {

		if(null == buffer) {
			return -1;
		}

		int pos = buffer.position();
		for(int i = 0; i < pos; i++) {
			if(b == buffer.get(i)) {
				return i;
			}
		}
		return -1;
	}

	/*
	 * (non-Javadoc)
	 * 
	 * @see com.wutianyi.nio.interfaces.InputQueue#isEmpty()
	 */
	@Override
	public boolean isEmpty() {

		return (null == buffer) || (buffer.position() == 0);
	}

}
